package org.jjj.car.service.impl;

import org.jjj.basic.utils.LoginContext;
import org.jjj.basic.utils.ResultAjax;
import org.jjj.basic.utils.VelocityUtils;
import org.jjj.car.domain.Car;
import org.jjj.car.domain.CarDetail;
import org.jjj.car.domain.CarOnlineAuditLog;
import org.jjj.car.domain.CarType;
import org.jjj.car.es.doc.CarDoc;
import org.jjj.car.es.repository.CarDocRepository;
import org.jjj.car.mapper.CarDetailMapper;
import org.jjj.car.mapper.CarMapper;
import org.jjj.car.mapper.CarOnlineAuditLogMapper;
import org.jjj.car.mapper.CarResourcesMapper;
import org.jjj.car.service.ICarService;
import org.jjj.basic.service.impl.BaseServiceImpl;
import org.jjj.org.domain.Employee;
import org.jjj.org.domain.Shop;
import org.jjj.org.service.IBaiduAiService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;


/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author jiangjianjun
 * @since 2022-11-03
 */
@Service
public class CarServiceImpl extends BaseServiceImpl<Car> implements ICarService {
    @Autowired
    private CarDetailMapper carDetailMapper;
    @Autowired
    private CarResourcesMapper carResourcesMapper;
    @Autowired
    private IBaiduAiService baiduAiService;
    @Autowired
    private CarOnlineAuditLogMapper carOnlineAuditLogMapper;
    @Autowired
    private CarMapper carMapper;
    @Autowired
    private CarDocRepository carDocRepository;
    //静态页面的模板路径和生成路径
    @Value("${velocity.templateFilePathAndName}")
    private String templateFilePathAndName;
    @Value("${velocity.targetFilePathAndName}")
    private String targetFilePathAndName;
    /**
     * 前端新增车辆后后端需要保存信息到数据库中
     * @param car
     */
    @Override
    @Transactional
    public void add(Car car) {
        //1.调用百度AI自动审核:封面，title，info基本信息
        //获得CarDetail对象
        CarDetail carDetail = car.getCarDetail();
        String authTest = car.getTitle()+""+carDetail.getInfo();
        ResultAjax resultAjax = baiduAiService.audit(authTest, car.getCover(), null);
        //2.封装审核日志新增到数据库
        CarOnlineAuditLog carOnlineAuditLog = new CarOnlineAuditLog();
        //设置审核时间
        carOnlineAuditLog.setAuditTime(new Date());
        //根据审核结果来设置状态
        if (resultAjax.getSuccess()){
            carOnlineAuditLog.setState(1);
            carOnlineAuditLog.setNote("自动审核通过！");
        }else {
            carOnlineAuditLog.setState(2);
            carOnlineAuditLog.setNote("自动审核失败！原因:"+resultAjax.getMessage());
        }
        //3.设置新增车辆的其他信息并保存到数据库
        //3.1设置新增车辆时间
        car.setCreatetime(new Date());
        //3.2设置状态：0下架，1上架
        car.setState(0);
        //3.3设置审核状态 0-待审核 1-审核通过 2-审核驳回
        car.setAuditstate(carOnlineAuditLog.getState());
        //3.4设置车辆的店铺信息   - 获取当前登录用户所在的店铺信息
        //获取当前登录用户
        Employee loginAdmin = LoginContext.getLoginAdmin();
        car.setShopId(loginAdmin.getShop().getId());
        car.setShopname(loginAdmin.getShop().getName());
        //3.5设置销售人员信息 - 当前登录用户就是销售人员
        car.setSellerId(loginAdmin.getId());
        //将信息保存到数据库
        super.add(car);
        //4.保存carDetail的信息
        //新增的是哪个车的信息
        carDetail.setCarId(car.getId());
        //车的标题
        carDetail.setCartitle(car.getTitle());
        //保存到车的细则表中
        carDetailMapper.insert(carDetail);
        //5.保存审核日志到数据库中
        carOnlineAuditLog.setCarId(car.getId());
        carOnlineAuditLogMapper.insert(carOnlineAuditLog);
    }

    /**
     * 删除对象信息
     *   删除车辆信息的同时需要删除：
     *   1.车辆资源表中相关联的信息
     *   2.车辆细节表中的相关信息
     * @param id
     */
    @Override
    @Transactional
    public void deleteById(Serializable id) {
        //1.根据id删除car表信息
        super.deleteById(id);
        //2.根据carId删除细节表中数据
        Long carId = (Long)id;
        carDetailMapper.deleteByCarId(carId);
        //3.根据carId删除资源表中数据
        carResourcesMapper.deleteByCarId(carId);
    }

    /**
     * 车辆上架逻辑处理
     * @param ids
     */
    @Override
    @Transactional
    public void onsale(List<Long> ids) {
        //1.前端传来的参数校验，判断ids对应的车辆的审核状态是否为通过，因为只有审核通过的车辆才能上架
        //方案一（采取）:简单粗暴，只要其中有一辆没通过就返回；方案二：跳过没通过审核的，上架审核通过的
        if (ids==null || ids.size()==0){
            throw new RuntimeException("没有选中要上架的车辆，请检查后重新提交上架！");
        }
        //根据ids去数据库查询出车辆通过审核的个数，判断是否与ids的长度相等
        Integer auditedCount = carMapper.getAuditedCount(ids);
        if (auditedCount!=ids.size()){
            throw new RuntimeException("有未通过审核的车辆，请检查后重新提交上架！");
        }
        //2.将车辆信息添加到es中一份，方便门户网站用户查看
        List<CarDoc> carDocs = buildESCarDocObj(ids);
        carDocRepository.saveAll(carDocs);
        //3.修改数据库的状态：上架，上架时间
        carMapper.onsale(ids);
        //4.在日志表中记录这一次上架记录:每一辆车信息对应一条记录
        addLogs(ids,3);
        //5.通过velocity生成车辆的详情静态页面，供门户网站用户来查看车辆详情
        staticPages(ids);
    }

    /**
     * 页面静态化模板生成车辆的详情页
     * @param ids
     */
    private void staticPages(List<Long> ids) {
        //每辆车都需要个详情页面
        ids.forEach(carId->{
            //去数据库查询车辆信息，用来渲染静态页面
            //设置模板类容:car
            Car car = carMapper.selectById(carId);
            //引用的模板的路径放到配置文件中templateFilePathAndName
            //静态页面生成的物理路径
            String targetFilePathAndName = this.targetFilePathAndName + carId + ".html";
            //调用模板引擎方法生成静态页面
            VelocityUtils.staticByTemplate(car,templateFilePathAndName,targetFilePathAndName);
        });
    }

    /**
     * 车辆下架逻辑处理
     * @param ids
     */
    @Override
    @Transactional
    public void offsale(List<Long> ids) {
        //1.前端传来的参数校验
        if (ids==null || ids.size()==0){
            throw new RuntimeException("没有选中要下架的车辆，请检查后重新提交下架请求！");
        }
        //2.将车辆信息从es中删除，门户网站用户只能查看到上架的车辆信息
        //从es中删除数据 deleteAll方法需要传入一个集合,集合中只要有id就可以了
        List<CarDoc> docs = new ArrayList<>();
        for (Long id : ids) {
            CarDoc carDoc = new CarDoc();
            carDoc.setId(id);
            docs.add(carDoc);
        }
        carDocRepository.deleteAll(docs);
        //3.修改数据库的状态：下架，下架时间
        carMapper.offsale(ids);
        //4.在日志表中记录这一次下架记录
        addLogs(ids,4);
        //5.删除相关联的车辆详情静态页面
        ids.forEach(carId->{
            //静态页面的存放路径
            String targetFilePathAndName = this.targetFilePathAndName + carId + ".html";
            File file = new File(targetFilePathAndName);
            file.delete();
        });
    }
/**
 * CarDoc中的数据来自于数据库的四张表
 * 用来渲染门户网站列表页面的数据
 */
    private List<CarDoc> buildESCarDocObj(List<Long> ids){
        // 方案一:循环ids,每次循环都去数据库进行查询car,查询type,shop detail
        // 方案二:一个语句查询出该ids对应的4张表的数据,关联查询 - 采用这个方案
        List<CarDoc> docs = new ArrayList<>();
        //从数据库中查询相关数据
        List<Car> cars = carMapper.getCarDocData(ids);
        for (Car car : cars) {
            CarDoc carDoc = new CarDoc();
            // 快速复制对象 - 前提是两个对象的属性名和类型都是一样的
            BeanUtils.copyProperties(car,carDoc);
            //设置店铺信息
            Shop shop = car.getShop();
            if (Objects.nonNull(shop)){
                carDoc.setShopId(shop.getId());
                carDoc.setShopName(shop.getName());
                carDoc.setShopAddress(shop.getAddress());
            }
            //设置类型信息
            CarType type = car.getType();
            if (Objects.nonNull(type)){
                carDoc.setTypeId(type.getId());
                carDoc.setTypeName(type.getName());
            }
            //设置详情信息info
            CarDetail carDetail = car.getCarDetail();
            if (Objects.nonNull(carDetail)){
                carDoc.setCarInfo(carDetail.getInfo());
            }
            //放入docs中
            docs.add(carDoc);
        }
        return docs;
    }
    /**
     * 抽取的批量添加日志的方法
     * @param ids
     * @param state
     */
    private void addLogs(List<Long>ids,Integer state){
        //获取当前登录对象：上架操作人
        Employee loginAdmin = LoginContext.getLoginAdmin();
        String note = state ==3?"上架":"下架";
        List<CarOnlineAuditLog> logs = new ArrayList<>();
        for (Long id : ids) {
            CarOnlineAuditLog log = new CarOnlineAuditLog();
            log.setCarId(id);
            log.setNote(loginAdmin.getUsername()+"对车辆id为"+id+"进行了"+note);
            log.setState(state);
            log.setAuditTime(new Date());
            log.setAuditId(loginAdmin.getId());
            //添加到数组中
            logs.add(log);
        }
        //批量新增到数据库
        carOnlineAuditLogMapper.batchInsert(logs);
    }
}
